﻿// Decompiled with JetBrains decompiler
// Type: Microsoft.InfoCards.RequestSecurityTokenResponseHelper
// Assembly: infocard, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// MVID: 8E14765A-6610-409A-BA36-099A0642905D
// Assembly location: E:\git\ALLIDA\windll\infocard.exe

using Microsoft.InfoCards.Diagnostics;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IdentityModel.Policy;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Security.Cryptography;
using System.ServiceModel.Security.Tokens;
using System.Xml;

namespace Microsoft.InfoCards
{
  internal static class RequestSecurityTokenResponseHelper
  {
    private static SecurityToken s_noProofToken = (SecurityToken) new UserNameSecurityToken("noproof", "noproof", "noproof");

    private static RequestSecurityTokenResponseHelper.RequestSecurityTokenResponse ReadRequestSecurityTokenResponse(
      XmlDictionaryReader reader,
      SecurityTokenSerializer tokenSerializer,
      SecurityTokenResolver resolver,
      ProtocolProfile profile)
    {
      InfoCardTrace.Assert(null != reader, "null reader");
      InfoCardTrace.Assert(null != tokenSerializer, "null tokenSerializer");
      RequestSecurityTokenResponseHelper.RequestSecurityTokenResponse securityTokenResponse = new RequestSecurityTokenResponseHelper.RequestSecurityTokenResponse();
      if (XmlNames.WSSpecificationVersion.WSTrustOasis2007 == profile.WSTrust.Version)
        reader.ReadFullStartElement(profile.WSTrust.RequestSecurityTokenResponseCollection, profile.WSTrust.Namespace);
      reader.ReadFullStartElement(profile.WSTrust.RequestSecurityTokenResponse, profile.WSTrust.Namespace);
      bool flag1 = false;
      bool flag2 = false;
      bool flag3 = false;
      bool flag4 = false;
      bool flag5 = false;
      bool flag6 = false;
      bool flag7 = false;
      bool flag8 = false;
      bool flag9 = false;
      bool flag10 = false;
      bool flag11 = false;
      securityTokenResponse.Created = DateTime.UtcNow;
      securityTokenResponse.Expires = new DateTime(DateTime.MaxValue.Ticks - TimeSpan.FromDays(2.0).Ticks, DateTimeKind.Utc);
      if (!reader.IsStartElement())
        throw InfoCardTrace.ThrowHelperError((Exception) new XmlException(SR.GetString("ServiceSTSCommunicationFailed")));
      while (reader.IsStartElement())
      {
        if (reader.IsStartElement(profile.WSTrust.TokenType, profile.WSTrust.Namespace))
        {
          if (flag1)
            throw InfoCardTrace.ThrowHelperError((Exception) new XmlException(SR.GetString("MultipleTokenTypeElementsFound")));
          securityTokenResponse.TokenType = reader.ReadElementString();
          flag1 = true;
        }
        else if (reader.IsStartElement(profile.WSTrust.KeySize, profile.WSTrust.Namespace))
        {
          if (flag3)
            throw InfoCardTrace.ThrowHelperError((Exception) new XmlException(SR.GetString("MultipleKeySizeElementsFound")));
          int num = reader.ReadElementContentAsInt();
          if (num <= 0)
            throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("KeySizeMustBeGreaterThanZero")));
          securityTokenResponse.KeySize = num;
          flag3 = true;
        }
        else if (reader.IsStartElement(profile.WSTrust.KeyType, profile.WSTrust.Namespace))
        {
          if (flag2)
            throw InfoCardTrace.ThrowHelperError((Exception) new XmlException(SR.GetString("MultipleKeySizeElementsFound")));
          string uriString = reader.ReadElementContentAsString();
          Uri uri = new Uri(uriString);
          if (profile.WSTrust.KeyTypeSymmetric.Equals((object) uri))
            securityTokenResponse.KeyType = new SecurityKeyTypeInternal?(SecurityKeyTypeInternal.SymmetricKey);
          else if (profile.WSTrust.KeyTypeAsymmetric.Equals((object) uri))
            securityTokenResponse.KeyType = new SecurityKeyTypeInternal?(SecurityKeyTypeInternal.AsymmetricKey);
          else if (profile.WSTrust.KeyTypeBearer.Equals((object) uri))
            securityTokenResponse.KeyType = new SecurityKeyTypeInternal?(SecurityKeyTypeInternal.NoKey);
          else
            throw InfoCardTrace.ThrowHelperError((Exception) new XmlException(SR.GetString("KeyTypeNotRecognized", (object) uriString)));
          flag2 = true;
        }
        else if (reader.IsStartElement(profile.WSTrust.Lifetime, profile.WSTrust.Namespace))
        {
          if (flag6)
            throw InfoCardTrace.ThrowHelperError((Exception) new XmlException(SR.GetString("MultipleLifetimeElementsFound")));
          reader.ReadStartElement();
          if (reader.IsStartElement("Created", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"))
            securityTokenResponse.Created = reader.ReadElementContentAsDateTime().ToUniversalTime();
          if (reader.IsStartElement("Expires", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"))
            securityTokenResponse.Expires = reader.ReadElementContentAsDateTime().ToUniversalTime();
          reader.ReadEndElement();
          flag6 = true;
        }
        else if (reader.IsStartElement(profile.WSTrust.RequestedSecurityToken, profile.WSTrust.Namespace))
        {
          if (flag7)
            throw InfoCardTrace.ThrowHelperError((Exception) new XmlException(SR.GetString("MultipleRequestedSecurityTokenElementsFound")));
          reader.ReadStartElement();
          reader.MoveToElement();
          XmlDocument xmlDocument = new XmlDocument();
          securityTokenResponse.IssuedTokenElement = xmlDocument.ReadNode((XmlReader) reader) as XmlElement;
          reader.ReadEndElement();
          flag7 = true;
        }
        else if (reader.IsStartElement(profile.WSTrust.RequestedProofToken, profile.WSTrust.Namespace))
        {
          if (flag8)
            throw InfoCardTrace.ThrowHelperError((Exception) new XmlException(SR.GetString("MultipleRequestedProofTokenElementsFound")));
          reader.ReadStartElement();
          if (reader.IsStartElement(profile.WSTrust.ComputedKey, profile.WSTrust.Namespace))
          {
            securityTokenResponse.ComputedKeyAlgorithm = reader.ReadElementString();
            if (profile.WSTrust.ComputedKeyAlgorithm != securityTokenResponse.ComputedKeyAlgorithm)
              throw InfoCardTrace.ThrowHelperError((Exception) new NotImplementedException(SR.GetString("OnlyPSha1SupportedCurrently", (object) securityTokenResponse.ComputedKeyAlgorithm)));
          }
          else
            securityTokenResponse.ProofToken = tokenSerializer.ReadToken((XmlReader) reader, resolver);
          reader.ReadEndElement();
          flag8 = true;
        }
        else if (reader.IsStartElement(profile.WSTrust.Entropy, profile.WSTrust.Namespace))
        {
          if (flag10)
            throw InfoCardTrace.ThrowHelperError((Exception) new XmlException(SR.GetString("MultipleEntropyElementsFound")));
          reader.ReadStartElement();
          securityTokenResponse.EntropyToken = tokenSerializer.ReadToken((XmlReader) reader, resolver);
          reader.ReadEndElement();
          flag10 = true;
        }
        else if (reader.IsStartElement("RequestedDisplayToken", "http://schemas.xmlsoap.org/ws/2005/05/identity"))
        {
          if (flag9)
            throw InfoCardTrace.ThrowHelperError((Exception) new XmlException(SR.GetString("MultipleRequestedDisplayTokenElementsFound")));
          securityTokenResponse.DisplayToken = RequestSecurityTokenResponseHelper.CreateDisplayToken(reader);
          flag9 = true;
        }
        else if (reader.IsStartElement(profile.WSTrust.RequestedAttachedReference, profile.WSTrust.Namespace))
        {
          if (flag4)
            throw InfoCardTrace.ThrowHelperError((Exception) new XmlException(SR.GetString("MultipleRequestedAttachedReferenceElementsFound")));
          reader.ReadStartElement();
          securityTokenResponse.RequestedAttachedReference = tokenSerializer.ReadKeyIdentifierClause((XmlReader) reader);
          reader.ReadEndElement();
          flag4 = true;
        }
        else if (reader.IsStartElement(profile.WSTrust.RequestedUnattachedReference, profile.WSTrust.Namespace))
        {
          if (flag5)
            throw InfoCardTrace.ThrowHelperError((Exception) new XmlException(SR.GetString("MultipleRequestedUnattachedReferenceElementsFound")));
          reader.ReadStartElement();
          securityTokenResponse.RequestedUnattachedReference = tokenSerializer.ReadKeyIdentifierClause((XmlReader) reader);
          reader.ReadEndElement();
          flag5 = true;
        }
        else if (reader.IsStartElement(profile.WSTrust.RequestType, profile.WSTrust.Namespace))
        {
          if (flag11)
            throw InfoCardTrace.ThrowHelperError((Exception) new XmlException(SR.GetString("MultipleRequestTypeElementsFound")));
          securityTokenResponse.RequestType = reader.ReadElementContentAsString();
          if (profile.WSTrust.IssueRequestType != securityTokenResponse.RequestType)
            throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("OnlyIssueRequestTypeSupported", (object) securityTokenResponse.RequestType, (object) profile.WSTrust.IssueRequestType)));
          flag11 = true;
        }
        else
          reader.Skip();
      }
      reader.ReadEndElement();
      if (XmlNames.WSSpecificationVersion.WSTrustOasis2007 == profile.WSTrust.Version)
      {
        if (!(profile.WSTrust.RequestSecurityTokenResponseCollection == reader.LocalName) || !(profile.WSTrust.Namespace == reader.NamespaceURI) || reader.NodeType != XmlNodeType.EndElement)
          throw InfoCardTrace.ThrowHelperError((Exception) new XmlException(SR.GetString("ServiceSTSCommunicationFailed")));
        reader.ReadEndElement();
      }
      return securityTokenResponse;
    }

    public static GenericXmlSecurityToken ProcessBearerTokenData(
      XmlDictionaryReader reader,
      SecurityTokenSerializer tokenSerializer,
      SecurityTokenResolver resolver,
      ProtocolProfile profile,
      out DisplayToken displayToken)
    {
      RequestSecurityTokenResponseHelper.RequestSecurityTokenResponse securityTokenResponse = RequestSecurityTokenResponseHelper.ReadRequestSecurityTokenResponse(reader, tokenSerializer, resolver, profile);
      displayToken = securityTokenResponse.DisplayToken ?? new DisplayToken();
      securityTokenResponse.ValidateRstrContents(SecurityKeyTypeInternal.NoKey);
      SecurityToken noProofToken = RequestSecurityTokenResponseHelper.s_noProofToken;
      return new GenericXmlSecurityToken(securityTokenResponse.IssuedTokenElement, noProofToken, securityTokenResponse.Created, securityTokenResponse.Expires, securityTokenResponse.RequestedAttachedReference, securityTokenResponse.RequestedUnattachedReference, (ReadOnlyCollection<IAuthorizationPolicy>) null);
    }

    public static GenericXmlSecurityToken ProcessSymmetricTokenData(
      XmlDictionaryReader reader,
      SecurityTokenSerializer tokenSerializer,
      SecurityTokenResolver resolver,
      byte[] clientEntropyForSymmetric,
      ProtocolProfile profile,
      out DisplayToken displayToken)
    {
      RequestSecurityTokenResponseHelper.RequestSecurityTokenResponse securityTokenResponse = RequestSecurityTokenResponseHelper.ReadRequestSecurityTokenResponse(reader, tokenSerializer, resolver, profile);
      displayToken = securityTokenResponse.DisplayToken ?? new DisplayToken();
      securityTokenResponse.ValidateRstrContents(SecurityKeyTypeInternal.SymmetricKey);
      if (securityTokenResponse.EntropyToken != null)
      {
        InfoCardTrace.Assert(profile.WSTrust.ComputedKeyAlgorithm == securityTokenResponse.ComputedKeyAlgorithm, "We already made sure it is PSHA1 while processing RSTR");
        BinarySecretSecurityToken entropyToken = securityTokenResponse.EntropyToken as BinarySecretSecurityToken;
        if (entropyToken == null)
          throw InfoCardTrace.ThrowHelperError((Exception) new TrustExchangeException(SR.GetString("InvalidEntropyContents")));
        int num = clientEntropyForSymmetric.Length * 8;
        if (securityTokenResponse.GetIntelligentKeySize(true, num) != num)
          throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException("SymmetricProofKeyLengthMismatch"));
        byte[] combinedKey = RequestSecurityTokenResponseHelper.RequestSecurityTokenResponse.ComputeCombinedKey(clientEntropyForSymmetric, entropyToken.GetKeyBytes(), num);
        securityTokenResponse.ProofToken = (SecurityToken) new BinarySecretSecurityToken(combinedKey);
      }
      else if (securityTokenResponse.ProofToken == null)
      {
        byte[] key = clientEntropyForSymmetric;
        securityTokenResponse.ProofToken = (SecurityToken) new BinarySecretSecurityToken(key);
      }
      return new GenericXmlSecurityToken(securityTokenResponse.IssuedTokenElement, securityTokenResponse.ProofToken, securityTokenResponse.Created, securityTokenResponse.Expires, securityTokenResponse.RequestedAttachedReference, securityTokenResponse.RequestedUnattachedReference, (ReadOnlyCollection<IAuthorizationPolicy>) null);
    }

    public static GenericXmlSecurityToken ProcessAsymmetricTokenData(
      XmlDictionaryReader reader,
      RSA rsa,
      SecurityTokenSerializer tokenSerializer,
      SecurityTokenResolver resolver,
      ProtocolProfile profile,
      out DisplayToken displayToken)
    {
      InfoCardTrace.Assert(null != rsa, "null rsa");
      RequestSecurityTokenResponseHelper.RequestSecurityTokenResponse securityTokenResponse = RequestSecurityTokenResponseHelper.ReadRequestSecurityTokenResponse(reader, tokenSerializer, resolver, profile);
      displayToken = securityTokenResponse.DisplayToken ?? new DisplayToken();
      securityTokenResponse.ValidateRstrContents(SecurityKeyTypeInternal.AsymmetricKey);
      SecurityToken proofToken = (SecurityToken) new RsaSecurityToken(rsa);
      return new GenericXmlSecurityToken(securityTokenResponse.IssuedTokenElement, proofToken, securityTokenResponse.Created, securityTokenResponse.Expires, securityTokenResponse.RequestedAttachedReference, securityTokenResponse.RequestedUnattachedReference, (ReadOnlyCollection<IAuthorizationPolicy>) null);
    }

    private static DisplayToken CreateDisplayToken(XmlDictionaryReader reader)
    {
      InfoCardTrace.Assert(null != reader, "null reader");
      DisplayToken displayToken = new DisplayToken();
      XmlReader reader1 = InfoCardSchemas.CreateReader(reader.ReadOuterXml());
      try
      {
        reader1.ReadStartElement("RequestedDisplayToken", "http://schemas.xmlsoap.org/ws/2005/05/identity");
        reader1.ReadStartElement("DisplayToken", "http://schemas.xmlsoap.org/ws/2005/05/identity");
        while (reader1.IsStartElement())
        {
          if (reader1.IsStartElement("DisplayClaim", "http://schemas.xmlsoap.org/ws/2005/05/identity"))
          {
            List<DisplayClaim> claimList = new List<DisplayClaim>();
            while (reader1.IsStartElement())
            {
              if (reader1.IsStartElement("DisplayClaim", "http://schemas.xmlsoap.org/ws/2005/05/identity"))
              {
                DisplayClaim displayClaim = RequestSecurityTokenResponseHelper.ReadDisplayClaim(reader1);
                if (displayClaim != null)
                  claimList.Add(displayClaim);
              }
              else
                reader1.Skip();
            }
            displayToken = new DisplayToken(claimList);
          }
          else if (reader1.IsStartElement("DisplayTokenText", "http://schemas.xmlsoap.org/ws/2005/05/identity"))
          {
            string attribute = reader1.GetAttribute("MimeType");
            string displayString = reader1.ReadElementContentAsString();
            if (!string.IsNullOrEmpty(displayString) && !string.IsNullOrEmpty(attribute))
              displayToken = new DisplayToken(displayString, attribute);
          }
          else
            reader1.Skip();
        }
        reader1.ReadEndElement();
        reader1.ReadEndElement();
      }
      catch (Exception ex)
      {
        displayToken = (DisplayToken) null;
        if (InfoCardTrace.IsFatal(ex))
          throw;
      }
      return displayToken;
    }

    private static DisplayClaim ReadDisplayClaim(XmlReader reader)
    {
      if (!reader.IsStartElement("DisplayClaim", "http://schemas.xmlsoap.org/ws/2005/05/identity"))
        throw InfoCardTrace.ThrowHelperError((Exception) new XmlException(SR.GetString("UnexpectedElement")));
      string name = string.Empty;
      List<string> stringList = new List<string>();
      string description = string.Empty;
      string empty = string.Empty;
      string attribute = reader.GetAttribute("Uri", "http://schemas.xmlsoap.org/ws/2005/05/identity");
      if (string.IsNullOrEmpty(attribute))
        attribute = reader.GetAttribute("Uri");
      bool isEmptyElement = reader.IsEmptyElement;
      reader.ReadStartElement();
      if (!isEmptyElement)
      {
        while (reader.IsStartElement())
        {
          if (reader.IsStartElement("DisplayTag", "http://schemas.xmlsoap.org/ws/2005/05/identity"))
            name = reader.ReadElementContentAsString();
          else if (reader.IsStartElement("DisplayValue", "http://schemas.xmlsoap.org/ws/2005/05/identity"))
            stringList.Add(reader.ReadElementContentAsString());
          else if (reader.IsStartElement("Description", "http://schemas.xmlsoap.org/ws/2005/05/identity"))
            description = reader.ReadElementContentAsString();
          else
            reader.Skip();
        }
        reader.ReadEndElement();
      }
      return new DisplayClaim(name, stringList, description, attribute);
    }

    private class RequestSecurityTokenResponse
    {
      private DateTime m_created = DateTime.UtcNow;
      private DateTime m_expires = DateTime.UtcNow.AddHours(1.0);
      private int m_keySize;
      private bool m_keySizeSpecified;
      private string m_requestType;
      private SecurityKeyIdentifierClause m_requestedAttachedReference;
      private SecurityKeyIdentifierClause m_requestedUnattachedReference;
      private SecurityToken m_entropyToken;
      private string m_computedKeyAlgorithm;
      private DisplayToken m_displayToken;
      private SecurityKeyTypeInternal? m_keyType;
      private string m_tokenType;
      private XmlElement m_issuedTokenElement;
      private SecurityToken m_proofToken;

      public int KeySize
      {
        set
        {
          this.m_keySize = value;
          this.m_keySizeSpecified = true;
        }
      }

      public int GetIntelligentKeySize(bool symmetric, int rstKeySize)
      {
        if (!symmetric)
          throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException());
        if (!this.m_keySizeSpecified)
          return rstKeySize;
        return this.m_keySize;
      }

      public SecurityKeyTypeInternal? KeyType
      {
        get
        {
          return this.m_keyType;
        }
        set
        {
          this.m_keyType = value;
        }
      }

      public DateTime Created
      {
        get
        {
          return this.m_created;
        }
        set
        {
          this.m_created = value;
        }
      }

      public DateTime Expires
      {
        get
        {
          return this.m_expires;
        }
        set
        {
          this.m_expires = value;
        }
      }

      public SecurityKeyIdentifierClause RequestedAttachedReference
      {
        get
        {
          return this.m_requestedAttachedReference;
        }
        set
        {
          this.m_requestedAttachedReference = value;
        }
      }

      public SecurityKeyIdentifierClause RequestedUnattachedReference
      {
        get
        {
          return this.m_requestedUnattachedReference;
        }
        set
        {
          this.m_requestedUnattachedReference = value;
        }
      }

      public string TokenType
      {
        set
        {
          this.m_tokenType = value;
        }
      }

      public SecurityToken EntropyToken
      {
        get
        {
          return this.m_entropyToken;
        }
        set
        {
          this.m_entropyToken = value;
        }
      }

      public string ComputedKeyAlgorithm
      {
        get
        {
          return this.m_computedKeyAlgorithm;
        }
        set
        {
          this.m_computedKeyAlgorithm = value;
        }
      }

      public DisplayToken DisplayToken
      {
        get
        {
          return this.m_displayToken;
        }
        set
        {
          this.m_displayToken = value;
        }
      }

      public XmlElement IssuedTokenElement
      {
        get
        {
          return this.m_issuedTokenElement;
        }
        set
        {
          this.m_issuedTokenElement = value;
        }
      }

      public SecurityToken ProofToken
      {
        get
        {
          return this.m_proofToken;
        }
        set
        {
          this.m_proofToken = value;
        }
      }

      public string RequestType
      {
        get
        {
          return this.m_requestType;
        }
        set
        {
          this.m_requestType = value;
        }
      }

      public static byte[] ComputeCombinedKey(
        byte[] requestorEntropy,
        byte[] issuerEntropy,
        int keySize)
      {
        if (requestorEntropy == null)
          throw InfoCardTrace.ThrowHelperArgumentNull(nameof (requestorEntropy));
        if (issuerEntropy == null)
          throw InfoCardTrace.ThrowHelperArgumentNull(nameof (issuerEntropy));
        InfoCardTrace.Assert(keySize > 0, "Keysize must be > 0");
        return new Psha1DerivedKeyGenerator(requestorEntropy).GenerateDerivedKey(new byte[0], issuerEntropy, keySize, 0);
      }

      public void ValidateRstrContents(SecurityKeyTypeInternal keyTypeExpected)
      {
        if (this.IssuedTokenElement == null)
          throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("NoIssuedTokenXml")));
        if (this.KeyType.HasValue)
        {
          SecurityKeyTypeInternal securityKeyTypeInternal = keyTypeExpected;
          SecurityKeyTypeInternal? keyType = this.KeyType;
          if ((securityKeyTypeInternal != keyType.GetValueOrDefault() ? 1 : (!keyType.HasValue ? 1 : 0)) != 0)
            throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("ProofKeyTypeMismatch")));
        }
        if (keyTypeExpected == SecurityKeyTypeInternal.SymmetricKey)
          return;
        if (SecurityKeyTypeInternal.AsymmetricKey == keyTypeExpected)
        {
          if (this.ProofToken != null)
            throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("ProofTokenXmlUnexpectedInRstr")));
        }
        else
        {
          InfoCardTrace.Assert(SecurityKeyTypeInternal.NoKey == keyTypeExpected, "Bad enum member for SecurityKeyTypeInternal");
          if (this.ProofToken != null)
            throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("ProofTokenXmlUnexpectedInRstr")));
        }
      }
    }
  }
}
